package com.wsc.personalblog.service.impl;

import com.wsc.personalblog.DTO.LeaveAMsgDTO;
import com.wsc.personalblog.DTO.LikeInfoDTO;
import com.wsc.personalblog.common.Constant;
import com.wsc.personalblog.entity.LeaveAMessage;
import com.wsc.personalblog.entity.LeaveAMessageExample;
import com.wsc.personalblog.mapper.LeaveAMessageMapper;
import com.wsc.personalblog.service.LeaveAMessageService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class LeaveAMessageServiceImpl implements LeaveAMessageService {

    @Autowired
    private LeaveAMessageMapper leaveAMessageMapper;
    @Autowired
    private LikeServiceImpl likeService;
    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public void removeLAMByIds(List<Integer> lAMIds) {
        LeaveAMessageExample leaveAMessageExample = new LeaveAMessageExample();
        LeaveAMessageExample.Criteria criteria = leaveAMessageExample.createCriteria();
        criteria.andIdIn(lAMIds);
        leaveAMessageMapper.deleteByExample(leaveAMessageExample);
    }

    @Override
    public void pubLAM(LeaveAMessage leaveAMessage) {
        leaveAMessage.setPubDate(LocalDateTime.now());
        leaveAMessageMapper.insertSelective(leaveAMessage);
        // 清空redis中缓存的留言id集合，
        redisTemplate.delete(Constant.LAM_ID_SET);
    }

    @Override
    public List<LeaveAMsgDTO> getAllLeaveAMsg(Integer pageNum , Integer userId) {
        List<LeaveAMsgDTO> leaveAMsgDTOs = leaveAMessageMapper.getLAM();
        if(leaveAMsgDTOs == null || leaveAMsgDTOs.size() == 0) {
            return null;
        }
        // 组合模型组成树型结构
        List<LeaveAMsgDTO> tree = tree(leaveAMsgDTOs,userId);
        tree = tree.stream().peek((item)-> {
            recursionCount(item,item);
        }).collect(Collectors.toList());
        // 重组成线程结构
        log.info("\n\n===================重组成线程结构开始======================");
        List<LeaveAMsgDTO> result = null;
        for (LeaveAMsgDTO item: tree) {
            result = new ArrayList();
            recursionRegroup(item,result);
            item.setChildren(result);
        }
        log.info("\n\n===================重组成线程结构已完毕======================");
        return tree;
    }
    // 递归重组
    private void recursionRegroup(LeaveAMsgDTO l, List<LeaveAMsgDTO> result){
        if(l.getChildren().size() == 0) return;
        List<LeaveAMsgDTO> children = l.getChildren();
        for (LeaveAMsgDTO obj :children) {
            // 生成线性结构
            result.add(obj);
            recursionRegroup(obj,result);
            // 解除父子关系
            obj.setChildren(null);
        }
    }
    // 递归计算子留言数
    private void recursionCount(LeaveAMsgDTO l1 , LeaveAMsgDTO l2){
        if(l1.getChildren().size() == 0) return;
        for (LeaveAMsgDTO obj :l1.getChildren()) {
            l2.setMsgCount(l2.getMsgCount()+1);
            recursionCount(obj,l2);
        }
    }
    // 生成树型结构
    private List<LeaveAMsgDTO> tree(List<LeaveAMsgDTO> leaveAMsgDTOs , Integer userId){
        if(leaveAMsgDTOs == null || leaveAMsgDTOs.size() == 0) return null;
        List<LeaveAMsgDTO> tree = new ArrayList<>();
        // 将所有节点传入HashMap，用于后续找到父节点
        HashMap<Integer, LeaveAMsgDTO> hm = new HashMap<>();
        for (LeaveAMsgDTO leaveAMsgDTO : leaveAMsgDTOs) {
            hm.put(leaveAMsgDTO.getId() , leaveAMsgDTO);
            Integer id = leaveAMsgDTO.getId();
            LikeInfoDTO l = likeService.getLAMLikeNumAndLikeStatus(id, userId);
            leaveAMsgDTO.setLikeInfoDTO(l);
        }
        // 遍历所有节点，如果没有父节点，直接加入到tree中，如果有，则加入到父节点中
        for (LeaveAMsgDTO leaveAMsgDTO : leaveAMsgDTOs) {
            Integer superId = leaveAMsgDTO.getSuperId();
            if(superId == null) {
                tree.add(leaveAMsgDTO);
                continue;
            }
            LeaveAMsgDTO superLeaveAMsgDTO = hm.get(superId);
            superLeaveAMsgDTO.getChildren().add(leaveAMsgDTO);
        }
        return tree;
    }

}
